#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "taster.h"
 

volatile uint8_t key_state;                                // debounced and inverted key state:
                                                  // bit = 1: key pressed
volatile uint8_t key_press;                                // key press detect
 
volatile uint8_t key_rpt;                                  // key long press and repeat
 
 
/*Drehgeber stuff*/ 

volatile int8_t  enc_delta_volume = 0;		// -128 ... 127
volatile int8_t  enc_delta_source = 0;		// -128 ... 127  

  static char enc_last_volume = 0x01;
    static char enc_last_source = 0x01;

 
//ISR( TIMER0_OVF_vect )                            // every 10ms
uint8_t
encoder_ISR (void)
{
  static uint8_t ct0, ct1, rpt;
  uint8_t i;
  

    
    /* Taster */
 
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 1e-3 + 0.5);  // preload for 1ms
 
  i = key_state ^ ~KEY_PIN;                       // key changed ?
  ct0 = ~( ct0 & i );                             // reset or count ct0
  ct1 = ct0 ^ (ct1 & i);                          // reset or count ct1
  i &= ct0 & ct1;                                 // count until roll over ?
  key_state ^= i;                                 // then toggle debounced state
  key_press |= key_state & i;                     // 0->1: key press detect
 
  if( (key_state & REPEAT_MASK) == 0 )            // check repeat function
     rpt = REPEAT_START;                          // start delay
  if( --rpt == 0 ){
    rpt = REPEAT_NEXT;                            // repeat delay
    key_rpt |= key_state & REPEAT_MASK;
  }
  
  /*Drehgeber Volume*/

  char j = 0;

  if( PHASE_A_VOL )
    j = 1;

  if( PHASE_B_VOL )
    j ^= 3;				// convert gray to binary

  j -= enc_last_volume;			// difference new - last

  if( j & 1 ){				// bit 0 = value (1)
    enc_last_volume += j;			// store new as next last

    enc_delta_volume += (j & 2) - 1;		// bit 1 = direction (+/-)
  }
  
    /*Drehgeber Source*/

  char k = 0;

  if( PHASE_B_SOU )
    k = 1;

  if( PHASE_A_SOU )
    k ^= 3;				// convert gray to binary

  k -= enc_last_source;			// difference new - last

  if( k & 1 ){				// bit 0 = value (1)
    enc_last_source += k;			// store new as next last

    enc_delta_source += (k & 2) - 1;		// bit 1 = direction (+/-)
  }
  



  
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed. Each pressed key is reported
// only once
//
uint8_t get_key_press( uint8_t key_mask )
{
  cli();                                          // read and clear atomic !
  key_mask &= key_press;                          // read key(s)
  key_press ^= key_mask;                          // clear key(s)
  sei();
  return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key has been pressed long enough such that the
// key repeat functionality kicks in. After a small setup delay
// the key is reported being pressed in subsequent calls
// to this function. This simulates the user repeatedly
// pressing and releasing the key.
//
uint8_t get_key_rpt( uint8_t key_mask )
{
  cli();                                          // read and clear atomic !
  key_mask &= key_rpt;                            // read key(s)
  key_rpt ^= key_mask;                            // clear key(s)
  sei();
  return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
// check if a key is pressed right now
//
uint8_t get_key_state( uint8_t key_mask )
 
{
  key_mask &= key_state;
  return key_mask;
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t get_key_short( uint8_t key_mask )
{
  cli();                                          // read key state and key press atomic !
  return get_key_press( ~key_state & key_mask );
}
 
///////////////////////////////////////////////////////////////////
//
uint8_t get_key_long( uint8_t key_mask )
{
  return get_key_press( get_key_rpt( key_mask ));
}

int8_t encode_read_volume( void )         // Encoder auslesen
{
  int8_t val;
 
  // atomarer Variablenzugriff  
  cli();
  val = enc_delta_volume;
  enc_delta_volume = 0;
  sei();
  return val;
}

int8_t encode_read_source( void )         // Encoder auslesen
{
  int8_t val;
 
  // atomarer Variablenzugriff  
  cli();
  val = enc_delta_source;
  //enc_delta_source = 0;
  enc_delta_source = val & 1;
  sei();
  return (val >> 1);
}

void encode_init( void )
{
  int8_t new;
 
  new = 0;
  if( PHASE_A_VOL )
    new = 3;
  if( PHASE_B_VOL )
    new ^= 1;                   // convert gray to binary
  enc_last_volume = new;                   // power on state
  enc_delta_volume = 0;
  
    new = 0;
  if( PHASE_A_SOU )
    new = 3;
  if( PHASE_B_SOU )
    new ^= 1;                   // convert gray to binary
  enc_last_source = new;                   // power on state
  enc_delta_source = 0;

}

